package com.gopay.common.event.store;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gopay.common.domain.report.Event;
import com.gopay.common.event.EventState;
import com.gopay.common.report.dao.MqEventInfoDAO;
import com.gopay.common.report.dao.MqEventTimeoutLogDAO;
import com.gopay.common.util.ContextUtil;
import com.gopay.common.util.NamedThreadFactory;


public class EventStorage {
    
    private final static Logger logger = LoggerFactory.getLogger(EventStorage.class);
    
    //保存事件列表的超时时间 5秒
    private static final long SAVE_EVENT_TIMEOUT=5;
        
	private static MqEventInfoDAO mqEventInfoDAO;
	private static MqEventTimeoutLogDAO mqEventTimeoutLogDAO;
	
	
	private static ExecutorService threadPool = Executors.newCachedThreadPool(new NamedThreadFactory("EventStorage"));
	
    
	public void store(Event e){	
	    //添加到事件队列
	    ArrayList<Event> eventList=new ArrayList<Event>();
	    Date now=new Date();
        e.setStat(EventState.PROGRESS.value); // 01-进行中
        e.setCreatedTs(now);
        e.setLastUpdTs(now);
	    eventList.add(e);
	    
	    //线程方式保存事件
	    saveEventByThread(eventList);
	}
	
	public void store(Collection<Event> events){	
	    Date now=new Date();
	    for(Event e : events){
	        e.setStat(EventState.PROGRESS.value); // 01-进行中
	        e.setCreatedTs(now);
	        e.setLastUpdTs(now);
	    }
	    //线程方式保存事件
        saveEventByThread(events);
	}
	
	/**
	 * 线程方式保存事件
	 * @throws TimeoutException 
	 * @throws ExecutionException 
	 * @throws InterruptedException 
	 */
	private void saveEventByThread(Collection<Event> eventList){
	    EventStoreTask task=new EventStoreTask(eventList,getMqEventInfoDAO());
	    FutureTask<Boolean> futureTask=new FutureTask<Boolean>(task);
	    threadPool.submit(futureTask);
	    
        try {
            futureTask.get(SAVE_EVENT_TIMEOUT, TimeUnit.SECONDS);
        } catch (Exception e) {//生产bug5期优化
            futureTask.cancel(true);// 参数设为true，向执行线程发送中断通知。否则，允许已经启动的线程继续执行直到完成任务。
            logger.error("线程方式保存事件超时了",e); 
            //保存超时日志
            saveTimeoutLogByThread(eventList);            
        }
	}
	
	/**
	 * 线程方式保存事件超时日志
	 * @param eventList
	 */
	private void saveTimeoutLogByThread(Collection<Event> eventList){
	    EventStoreTimeoutTask task=new EventStoreTimeoutTask(eventList,getMqEventTimeoutLogDAO());
        FutureTask<Boolean> futureTask=new FutureTask<Boolean>(task);
        threadPool.submit(futureTask);
        
        try {
            futureTask.get(SAVE_EVENT_TIMEOUT, TimeUnit.SECONDS);
        } catch (TimeoutException e) {  
            futureTask.cancel(true);// 参数设为true，向执行线程发送中断通知。否则，允许已经启动的线程继续执行直到完成任务。
            logger.error("线程方式保存事件Timeout日志超时了",e);
        }  catch (InterruptedException | ExecutionException e) {
            logger.error("线程方式保存事件Timeout日志 Error",e);
        }
    }
	
	private MqEventInfoDAO getMqEventInfoDAO(){
	    if(mqEventInfoDAO==null){
	        mqEventInfoDAO=(MqEventInfoDAO)ContextUtil.getBean("mqEventInfoDAO");
	        if(mqEventInfoDAO==null){
	            logger.error("common-x 获取bean=mqEventInfoDAO出错");
	        }
	    }
	    return mqEventInfoDAO;
	}
	
	private MqEventTimeoutLogDAO getMqEventTimeoutLogDAO(){ 
        if(mqEventTimeoutLogDAO==null){
            mqEventTimeoutLogDAO=(MqEventTimeoutLogDAO)ContextUtil.getBean("mqEventTimeoutLogDAO");
            if(mqEventTimeoutLogDAO==null){
                logger.error("common-x 获取bean=mqEventTimeoutLogDAO出错");
            }
        }
        return mqEventTimeoutLogDAO;
    }
	
}

